package com.song.sparkstudy.stream;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.StorageLevels;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.streaming.Durations;
import org.apache.spark.streaming.api.java.JavaDStream;
import org.apache.spark.streaming.api.java.JavaPairDStream;
import org.apache.spark.streaming.api.java.JavaReceiverInputDStream;
import org.apache.spark.streaming.api.java.JavaStreamingContext;
import org.apache.spark.streaming.api.java.JavaStreamingContextFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import scala.Tuple2;


/**
 *    从网络获取制定的数据，然后遍历 rdd 然后存储到redis 里面
 * @author root
 *
 */
public class JavaRecoverableNetWordCount {
	
	private static final Pattern SPACE = Pattern.compile(" ");
	
	
	public static void main(String[] args) {
		
		final String ip ="127.0.0.1";
		final  int  port = 8888;
		final String checkpoint ="hdfs://song-dinfo:9000/check";
		
		JedisPoolHolder.init("192.168.2.252", 6379);
		
		JavaStreamingContextFactory factory = new JavaStreamingContextFactory() {
			
			@Override
			public JavaStreamingContext create() {
				// TODO Auto-generated method stub
				return createContext(ip, port, checkpoint);
			}
		};
	JavaStreamingContext  ssc = JavaStreamingContext.getOrCreate(checkpoint, factory);
	ssc.start();
	ssc.awaitTermination();
		
		
	}
	
	
	
	private static JavaStreamingContext createContext(String ip , int port , String check)
	{
		SparkConf conf = new SparkConf().setAppName("save app").setMaster("local[2]");
		JavaStreamingContext ssc = new JavaStreamingContext(conf, Durations.seconds(2));
		ssc.checkpoint(check);
		
		 JavaReceiverInputDStream<String> lines = ssc.socketTextStream(ip, port, StorageLevels.MEMORY_AND_DISK_SER);
	        JavaDStream<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
	            @Override
	            public Iterable<String> call(String x) {
	                return Arrays.asList(SPACE.split(x));
	            }
	        });
	        JavaPairDStream<String, Integer> wordCounts = words.mapToPair(new PairFunction<String, String, Integer>() {
	            @Override
	            public Tuple2<String, Integer> call(String s) {
	                return new Tuple2<String, Integer>(s, 1);
	            }
	        }).reduceByKey(new Function2<Integer, Integer, Integer>() {
	            @Override
	            public Integer call(Integer i1, Integer i2) {
	                return i1 + i2;
	            }
	        });
	      
	        wordCounts.foreach(new Function<JavaPairRDD<String,Integer>, Void>() {
				
				@Override
				public Void call(JavaPairRDD<String, Integer> rdd) throws Exception {
					List<Tuple2<String, Integer>> list =  rdd.collect();
					Jedis jedis =JedisPoolHolder.getInstance().getResource();
					for(Tuple2<String, Integer> t :list)
					{
						jedis.incrBy("word_"+t._1, t._2());
					}
					return null;
				}
			});
	        
		return ssc;
	}
	

}



class JedisPoolHolder {
    /** {@link JedisPool} */
    private static volatile JedisPool instance = null;

    /** redis ip */
    private static String ip;

    /** redis port */
    private static int port;

    /**
     * 初始化
     * <p>
     *
     * @param redisIp
     * @param redisPort
     */
    public static void init(String redisIp, int redisPort) {
        ip = redisIp;
        port = redisPort;
    }

    /**
     * 获取单例JedisPool
     * <p>
     *
     * @return {@link JedisPool}
     */
    public static JedisPool getInstance() {
        if (instance == null) {
            synchronized (JedisPoolHolder.class) {
                if (instance == null) {
                    JedisPoolConfig config = new JedisPoolConfig();
                    config.setMaxTotal(100);
                    config.setMinIdle(10);
                    config.setMaxIdle(10);
                    config.setMaxWaitMillis(2000);
                    config.setTestWhileIdle(false);
                    config.setTestOnBorrow(false);
                    config.setTestOnReturn(false);
                    instance = new JedisPool(config, ip, port);
                }
            }
        }
        return instance;
    }
}